package cn.lyjuan.payment.third.base.pay.chl.impl.weixin.util;

import cn.lyjuan.base.util.DigestUtils;
import cn.lyjuan.base.util.XmlUtils;
import cn.lyjuan.payment.third.base.pay.chl.impl.weixin.bean.WxChlCnf;
import cn.lyjuan.payment.third.base.pay.chl.impl.weixin.bean.WxNotifyReq;
import cn.lyjuan.payment.third.base.pay.cst.PayConst;
import cn.lyjuan.payment.third.base.pay.enums.SimpleStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by ly on 2015/1/27.
 */
@Slf4j
@Component("wxSDKNotify")
public class WxpayNotify {
    public static final String NOTIFY_RES_XML = "<xml><return_code>#code#</return_code><return_msg>#msg#</return_msg></xml>";

    /**
     * 解析微信支付通知数据
     *
     * @param xml 通知内容
     * @return
     */
    public static Map<String, String> parseNotifyData(String xml) {
        Map<String, String> params = new HashMap<String, String>();

        // 成功的信息
        params.put("appid", XmlUtils.getMember(xml, "appid"));
        params.put("bank_type", XmlUtils.getMember(xml, "bank_type"));
        params.put("cash_fee", XmlUtils.getMember(xml, "cash_fee"));
        params.put("fee_type", XmlUtils.getMember(xml, "fee_type"));
        params.put("is_subscribe", XmlUtils.getMember(xml, "is_subscribe"));
        params.put("mch_id", XmlUtils.getMember(xml, "mch_id"));
        params.put("nonce_str", XmlUtils.getMember(xml, "nonce_str"));
        params.put("openid", XmlUtils.getMember(xml, "openid"));
        params.put("out_trade_no", XmlUtils.getMember(xml, "out_trade_no"));
        params.put("return_code", XmlUtils.getMember(xml, "return_code"));
        params.put("result_code", XmlUtils.getMember(xml, "result_code"));
        params.put("sign", XmlUtils.getMember(xml, "sign"));
        params.put("time_end", XmlUtils.getMember(xml, "time_end"));
        params.put("total_fee", XmlUtils.getMember(xml, "total_fee"));
        params.put("trade_type", XmlUtils.getMember(xml, "trade_type"));
        params.put("transaction_id", XmlUtils.getMember(xml, "transaction_id"));

        // 其他信息
        params.put("return_msg", XmlUtils.getMember(xml, "return_msg"));
        params.put("device_info", XmlUtils.getMember(xml, "device_info"));
        params.put("err_code", XmlUtils.getMember(xml, "err_code"));
        params.put("err_code_des", XmlUtils.getMember(xml, "err_code_des"));
        params.put("attach", XmlUtils.getMember(xml, "attach"));

        return params;
    }


    /**
     * 验证微信支付异步通知签名
     *
     * @param params
     * @return true签名匹配
     */
    public static boolean veryfyNotifySign(WxNotifyReq params, WxChlCnf cnf) {
        String sign = params.get("sign");
        // 排序拼接签名参数
        String signStr = WxUtils.sortParamForSign(params);
        signStr += "&key=" + cnf.getKey();
        // 根据密钥进行 MD5 签名
        String localSign = DigestUtils.md5LowerCase(signStr, PayConst.CHARSET);

        return localSign.equalsIgnoreCase(sign);
    }

    /**
     * 微信异步通知响应
     *
     * @param receiveSucc 是否返回接收通知成功
     * @return
     */
    public static String notifyRes(boolean receiveSucc) {
        return receiveSucc
                ? NOTIFY_RES_XML.replace("#code#", WxpaySubmit.SUCC).replace("#msg#", "sign mismatch")
                : NOTIFY_RES_XML.replace("#code#", WxpaySubmit.FAIL).replace("#msg#", "sign mismatch");
    }

    /**
     * 异步通知信息中错误描述信息
     *
     * @param params
     * @return
     */
    public static String notifyErrorMsg(Map<String, String> params) {
        // 解析交易状态
        String msg = params.get("return_msg");

        msg += params.get("err_code");

        msg += params.get("err_code_des");

        return msg;
    }

    /**
     * 从异步通知中解析交易状态
     *
     * @param params 支付渠道的交易状态
     * @return
     */
    public static SimpleStatusEnum parseNotifyPayStatus(Map<String, String> params) {
        // 成功
        if (WxpaySubmit.SUCC.equalsIgnoreCase(params.get("return_code"))
                && WxpaySubmit.SUCC.equalsIgnoreCase(params.get("result_code")))
            return SimpleStatusEnum.SUCC;

        return SimpleStatusEnum.UNKNOWN;
    }

    /**
     * 从通知信息中获取支付平台交易号
     *
     * @param req
     * @return
     */
    public static String parseTranNoFromNotify(Map<String, String> req) {
        return req.get("transaction_id");
    }
}
